package com.xiaolei.libraryktx

import android.app.Activity
import android.content.Intent
import android.content.SharedPreferences
import android.os.Build
import android.os.Bundle
import android.view.View
import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
import androidx.annotation.RequiresApi
import androidx.annotation.StringRes
import androidx.fragment.app.Fragment
import androidx.viewbinding.ViewBinding
import com.xiaolei.library.BuildConfig
import com.xiaolei.library.Exts.Ext
import com.xiaolei.library.common.ActivityResultFragment
import com.xiaolei.library.common.SPEditor
import java.io.File
import java.lang.IllegalStateException
import kotlin.reflect.KClass

/**
 * 启动页面
 *
 * @param klass   需要启动得类
 */
inline fun <reified T : Fragment> T.start(
    klass: KClass<out Activity>, noinline block: (Bundle.() -> Unit)? = null
)
{
    Ext.start(this, klass.java, if (block == null)
    {
        null
    } else
    {
        Bundle().apply {
            block.invoke(this)
        }
    })
}

/**
 * 启动页面返回结果
 *
 * @param klass   需要启动得类
 */
inline fun <reified T : Fragment> T.startForResult(
    klass: KClass<out Activity>, noinline bundle: (Bundle.() -> Unit)? = null, noinline onResult: ((respCode: Int, data: Intent?) -> Unit?)? = null
)
{
    Ext.startForResult(this, klass.java, if (bundle == null)
    {
        null
    } else
    {
        Bundle().apply(bundle)
    }, if (onResult == null)
    {
        null
    } else
    {
        ActivityResultFragment.OnActivityResult { resultCode, data ->
            onResult.invoke(resultCode, data)
        }
    })
}

/**
 * 设置界面为黑色标题栏文字的模式
 */
inline fun <reified T : Fragment> T.darkStatusModel()
{
    Ext.darkStatusModel(this.requireActivity())
}

/**
 * 设置界面为白色标题栏文字的模式
 */
inline fun <reified T : Fragment> T.lightStatusModel()
{
    Ext.lightStatusModel(this.requireActivity())
}

/**
 * 获取屏幕宽度
 */
inline fun <reified T : Fragment> T.getScreenWidth() = Ext.getScreenWidth(this.requireActivity())

/**
 * 获取屏幕高度
 */
inline fun <reified T : Fragment> T.getScreenHeight() = Ext.getScreenHeight(this.requireActivity())

/**
 * 单位换算 px 转 sp
 *
 * @param px      px像素单位
 * @return sp的单位
 */
inline fun <reified T : Fragment> T.px2sp(px: Int) = Ext.px2sp(requireActivity(), px)

/**
 * 单位换算 sp 转 px
 *
 * @param sp      sp单位
 * @return px像素单位
 */
inline fun <reified T : Fragment> T.sp2px(sp: Int) = Ext.sp2px(requireActivity(), sp)

/**
 * 单位换算 px 转 dp
 *
 * @param px      px像素
 * @return dp单位
 */
inline fun <reified T : Fragment> T.px2dp(px: Int) = Ext.px2dp(requireActivity(), px)

/**
 * 单位换算 dp 转 px
 *
 * @param dp      dp单位
 * @return px像素单位
 */
inline fun <reified T : Fragment> T.dp2px(dp: Int) = Ext.dp2px(requireActivity(), dp)

/**
 * 获取颜色
 *
 * @param res     颜色的资源id
 * @return 颜色的int值
 */
inline fun <reified T : Fragment> T.takeColor(@ColorRes res: Int) = Ext.getColor(requireActivity(), res)

/**
 * 获取Drawable
 * @param res 资源ID
 */
inline fun <reified T : Fragment> T.takeDrawable(@DrawableRes res: Int) = Ext.getDrawable(requireContext(), res)

/**
 * 获取字符串
 *
 * @param res     字符串的资源id
 * @return 字符串的值
 */
inline fun <reified T : Fragment> T.getString(@StringRes res: Int) = Ext.getString(requireActivity(), res)

/**
 * 快捷弹出吐司
 *
 * @param resId
 */
inline fun <reified T : Fragment> T.Toast(@StringRes resId: Int) = Ext.Toast(activity, resId)

/**
 * 快捷弹出吐司
 *
 * @param obj
 */
inline fun <reified T : Fragment> T.Toast(obj: Any) = Ext.Toast(activity, obj)


/**
 * 获取状态栏的高度
 */
inline fun <reified T : Fragment> T.getStatbarHeight() = Ext.getStatbarHeight(requireActivity())

inline fun <reified T : Fragment> T.spGet(key: String, defValue: Float): Float
{
    return Ext.spGet(requireActivity(), BuildConfig.SpFileName, key, defValue)
}

inline fun <reified T : Fragment> T.spGet(key: String, defValue: Int): Int
{
    return Ext.spGet(requireActivity(), BuildConfig.SpFileName, key, defValue)
}

inline fun <reified T : Fragment> T.spGet(key: String, defValue: Long): Long
{
    return Ext.spGet(requireActivity(), BuildConfig.SpFileName, key, defValue)
}

inline fun <reified T : Fragment> T.spGet(
    fileName: String, key: String, defValue: Set<String>
): Set<String>
{
    return Ext.spGet(requireActivity(), fileName, key, defValue)
}

inline fun <reified T : Fragment> T.spGet(key: String, defValue: String): String
{
    return Ext.spGet(requireActivity(), BuildConfig.SpFileName, key, defValue)
}

/**
 * 对SharedPreferences 进行存值取值
 */
inline fun <reified T : Fragment> T.spEdit(block: SPEditor)
{
    Ext.spEdit(requireActivity(), BuildConfig.SpFileName, block)
}

/**
 * 对SharedPreferences 进行存值取值
 */
inline fun <reified T : Fragment> T.spEdit(crossinline block: (SharedPreferences.Editor) -> Unit)
{
    Ext.spEdit(requireActivity(), BuildConfig.SpFileName) {
        block.invoke(it)
    }
}

/**
 * 弹出软键盘
 *
 * @param view    聚焦的控件
 */
inline fun <reified T : Fragment> T.showKeyboard(view: View)
{
    Ext.showKeyboard(requireActivity(), view)
}

/**
 * 获取图片存储位置
 */
inline fun <reified T : Fragment> T.getImgDir(): File
{
    return Ext.getImgDir(requireActivity())
}

/**
 * 获取临时文件存储位置
 */
inline fun <reified T : Fragment> T.getTmpDir(): File
{
    return Ext.getTmpDir(requireActivity())
}

/**
 * 弹窗
 *
 * @param title 标题
 */
inline fun <reified T : Fragment> T.Alert(title: String)
{
    Ext.Alert(requireActivity(), title)
}

/**
 * 弹窗
 *
 * @param title        标题
 * @param completeText 确认按钮
 */
inline fun <reified T : Fragment> T.Alert(title: String, completeText: String)
{
    Ext.Alert(requireActivity(), title, completeText)
}

/**
 * 弹窗
 *
 * @param title         标题
 * @param completeText  确认按钮
 * @param completeBlock 确认按钮点击事件
 */
inline fun <reified T : Fragment> T.Alert(
    title: String, completeText: String, noinline completeBlock: (() -> Unit)? = null
)
{
    Ext.Alert(requireActivity(), title, completeText, completeBlock)
}

/**
 * 弹窗
 *
 * @param title        标题
 * @param completeText 确认按钮
 * @param navigateText 第二个按钮
 */
inline fun <reified T : Fragment> T.Alert(
    title: String, completeText: String, navigateText: String
)
{
    Ext.Alert(requireActivity(), title, completeText, navigateText)
}

/**
 * 弹窗
 *
 * @param title         标题
 * @param completeText  确认按钮
 * @param navigateText  第二个按钮
 * @param completeBlock 确认按钮事件
 * @param navigateBlock 第二个按钮事件
 */
inline fun <reified T : Fragment> T.Alert(
    title: String, msg: String, completeText: String, noinline completeBlock: (() -> Unit)? = null, navigateText: String, noinline navigateBlock: (() -> Unit)? = null
)
{
    Ext.Alert(
        requireActivity(), title, msg, completeText, completeBlock, navigateText, navigateBlock
    )
}


/**
 * 判断我们的应用是否在电池优化白名单中
 */
@RequiresApi(api = Build.VERSION_CODES.M)
inline fun <reified T : Fragment> T.isIgnoringBatteryOptimizations() =
    Ext.isIgnoringBatteryOptimizations(activity)

/**
 * 申请加入电池优化白名单
 */
@RequiresApi(api = Build.VERSION_CODES.M)
inline fun <reified T : Fragment> T.requestIgnoreBatteryOptimizations() =
    Ext.requestIgnoreBatteryOptimizations(activity)

/**
 * 在Fragment里获取ViewBinding
 */
inline fun <reified T : ViewBinding> Fragment.viewBinding(): Lazy<T>
{
    return lazy {
        val klass = T::class.java
        val bind = klass.getDeclaredMethod("bind", View::class.java)
        val root = view ?: throw IllegalStateException("getView() == null")
        var viewBinding = root.tag as? ViewBinding?
        if (viewBinding == null)
        {
            viewBinding = bind.invoke(null, root) as ViewBinding
            root.tag = viewBinding
        }
        viewBinding as T
    }
}